import { useRef, useMemo } from 'react';
import { useFrame } from '@react-three/fiber';
import { MeshDistortMaterial } from '@react-three/drei';
import * as THREE from 'three';

// 根据轨道位置获取X坐标
const getLanePosition = (lane) => {
  return (lane - 1.5) * 3; // 与FloorNote组件的定位对应
};

// 根据准确度计算特效颜色
const getAccuracyColor = (accuracy) => {
  // 色彩从红(0xff0000)过渡到绿(0x00ff00)
  const red = Math.floor((1 - accuracy) * 255);
  const green = Math.floor(accuracy * 255);
  return new THREE.Color(red / 255, green / 255, 0);
};

// 根据按键获取颜色
const getKeyColor = (key) => {
  switch(key) {
    case 'q': return new THREE.Color(1, 0.3, 0.3); // 红色
    case 'w': return new THREE.Color(0.3, 1, 0.3); // 绿色
    case 'e': return new THREE.Color(0.3, 0.3, 1); // 蓝色
    case 'r': return new THREE.Color(1, 1, 0.3);   // 黄色
    case 'space': return new THREE.Color(1, 0.3, 1); // 紫色
    default: return new THREE.Color(1, 1, 1);      // 白色
  }
};

// 彩色波纹特效
const WaveEffect = ({ effect }) => {
  const meshRef = useRef();
  const materialRef = useRef();
  const startTime = useMemo(() => Date.now(), []);
  
  // 特效位置 (根据音符轨道)
  const position = useMemo(() => {
    const x = getLanePosition(effect.position);
    const z = -effect.time * 2; // 与FloorNote组件的Z轴定位相匹配
    return [x, 0.1, z];
  }, [effect.position, effect.time]);
  
  // 特效颜色 (根据按键和准确度)
  const baseColor = useMemo(() => {
    return getKeyColor(effect.key);
  }, [effect.key]);
  
  // 特效动画
  useFrame(() => {
    if (!meshRef.current) return;
    
    // 特效生命周期
    const age = (Date.now() - startTime) / 1000;
    const lifetime = 1.0; // 1秒生命周期
    
    if (age > lifetime) {
      meshRef.current.visible = false;
      return;
    }
    
    // 生命周期进度 (0-1)
    const progress = age / lifetime;
    
    // 扩散圆环动画
    meshRef.current.scale.set(
      1 + progress * 5,
      1,
      1 + progress * 5
    );
    
    // 淡出和颜色变化效果
    if (materialRef.current) {
      materialRef.current.opacity = 1 - progress;
      
      // 颜色变化效果 - 彩虹过渡
      const hue = (progress * 2) % 1;
      const rainbow = new THREE.Color().setHSL(hue, 1, 0.5);
      materialRef.current.color.lerp(rainbow, 0.5);
      materialRef.current.emissive.lerp(rainbow, 0.5);
    }
  });
  
  return (
    <mesh
      ref={meshRef}
      position={position}
      rotation={[-Math.PI / 2, 0, 0]}
    >
      <ringGeometry args={[0.3, 0.5, 32]} />
      <meshStandardMaterial
        ref={materialRef}
        color={baseColor}
        emissive={baseColor}
        emissiveIntensity={2}
        transparent
        opacity={1}
        side={THREE.DoubleSide}
      />
    </mesh>
  );
};

// 成功连击时的爆炸特效
const ExplosionEffect = ({ effect }) => {
  const groupRef = useRef();
  const startTime = useMemo(() => Date.now(), []);
  
  // 爆炸位置
  const position = useMemo(() => {
    const x = getLanePosition(effect.position);
    const z = -effect.time * 2;
    return [x, 0.5, z];
  }, [effect.position, effect.time]);
  
  // 生成多个飞散的粒子
  const particles = useMemo(() => {
    const count = 12;
    const items = [];
    
    for (let i = 0; i < count; i++) {
      // 随机方向和速度
      const angle = (i / count) * Math.PI * 2;
      const radius = 0.2 + Math.random() * 0.3;
      
      items.push({
        id: i,
        direction: new THREE.Vector3(
          Math.cos(angle) * radius,
          0.5 + Math.random() * 0.5,
          Math.sin(angle) * radius
        ),
        speed: 2 + Math.random() * 2,
        color: new THREE.Color().setHSL(i / count, 1, 0.5)
      });
    }
    
    return items;
  }, []);
  
  // 粒子动画
  useFrame(() => {
    if (!groupRef.current) return;
    
    const age = (Date.now() - startTime) / 1000;
    const lifetime = 1.5;
    
    if (age > lifetime) {
      groupRef.current.visible = false;
      return;
    }
    
    // 更新每个粒子的位置和大小
    groupRef.current.children.forEach((particle, i) => {
      const data = particles[i];
      
      // 移动粒子
      particle.position.x += data.direction.x * data.speed * 0.016;
      particle.position.y += (data.direction.y - age * 2) * data.speed * 0.016; // 添加重力效果
      particle.position.z += data.direction.z * data.speed * 0.016;
      
      // 缩小并淡出粒子
      const scale = Math.max(0, 1 - age / lifetime);
      particle.scale.set(scale, scale, scale);
      
      if (particle.material) {
        particle.material.opacity = Math.max(0, 1 - (age / lifetime) * 1.5);
      }
    });
  });
  
  // 只有在连击数较高且准确度高时才显示爆炸效果
  const shouldShow = useMemo(() => {
    return effect.combo > 5 && effect.accuracy > 0.7;
  }, [effect.combo, effect.accuracy]);
  
  if (!shouldShow) return null;
  
  return (
    <group ref={groupRef} position={position}>
      {particles.map((particle) => (
        <mesh key={particle.id}>
          <sphereGeometry args={[0.2, 8, 8]} />
          <meshStandardMaterial
            color={particle.color}
            emissive={particle.color}
            emissiveIntensity={2}
            transparent
            opacity={1}
          />
        </mesh>
      ))}
    </group>
  );
};

// 节拍波纹特效
const BeatEffect = ({ effect }) => {
  const meshRef = useRef();
  const materialRef = useRef();
  const startTime = useMemo(() => Date.now(), []);

  // 特效动画
  useFrame(() => {
    if (!meshRef.current) return;
    
    const age = (Date.now() - startTime) / 1000;
    const lifetime = 0.5; // 0.5秒生命周期
    
    if (age > lifetime) {
      meshRef.current.visible = false;
      return;
    }
    
    const progress = age / lifetime;
    
    // 扩散波纹
    meshRef.current.scale.set(
      1 + progress * 20,
      1 + progress * 20,
      1
    );
    
    if (materialRef.current) {
      materialRef.current.opacity = 0.5 * (1 - progress);
    }
  });
  
  return (
    <mesh
      ref={meshRef}
      rotation={[-Math.PI / 2, 0, 0]}
      position={[0, 0.01, 0]}
    >
      <ringGeometry args={[0.5, 0.6, 32]} />
      <meshBasicMaterial
        ref={materialRef}
        color="#ffffff"
        transparent
        opacity={0.5}
        side={THREE.DoubleSide}
      />
    </mesh>
  );
};

// 主特效组件
const HitEffects = ({ effectsQueue }) => {
  return (
    <group>
      {effectsQueue.map((effect, index) => {
        if (effect.type === 'hit') {
          return (
            <group key={`effect-${effect.time}-${index}`}>
              <WaveEffect effect={effect} />
              <ExplosionEffect effect={effect} />
            </group>
          );
        } else if (effect.type === 'beat') {
          return <BeatEffect key={`beat-${effect.time}-${index}`} effect={effect} />;
        }
        return null;
      })}
    </group>
  );
};

export default HitEffects; 